﻿using System;
using System.IO;
using System.Text;
using System.Reflection;
using System.Security.Cryptography;
#if SILVERLIGHT
using System.Windows.Browser;
#else
using System.Web;
#endif

using SBPweb.Forge.Contracts.Text;

namespace SBPweb.Forge.Cryptography
{

    public class CustomCryptographyProvider : ICryptographyProvider
    {

        #region Static declarations

        private const string PASSWORD_GUID = "0D7F0F5A-9D87-4a94-81BB-6FC311D0914D";
        private const string SALT_GUID = "4FB3D740-F4F0-4bad-B4B1-3149F9A10AB2";

        #endregion

        #region Private fields

        private static Encoding ENCODING = Encoding.UTF8;
        
        #endregion

        #region Constructor logic

        public CustomCryptographyProvider()
        {
            //cryptoStream = new MemoryStream();

            //using (CryptoStream cs = new CryptoStream(cryptoStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
            //{
            //    byte[] rawPlaintext = Encoding.Unicode.GetBytes(inputBox.Text);
            //    cs.Write(rawPlaintext, 0, rawPlaintext.Length);
            //    cs.FlushFinalBlock();
            //}
        }

        #endregion

        #region Methods

        public string Decrypt(string phrase)
        {
            return Decrypt(phrase, new Rfc2898DeriveBytes(PASSWORD_GUID, ENCODING.GetBytes(SALT_GUID.ToString())).GetBytes(16));
        }

        public string Decrypt<T>(string phrase, T salt)
        {
            return Decrypt(phrase, new Rfc2898DeriveBytes(PASSWORD_GUID, ENCODING.GetBytes(salt.ToString())).GetBytes(16));
        }

        private string Decrypt(string phrase, byte[] key)
        {
            AesManaged decryptor = new AesManaged();
            byte[] encryptedData = Convert.FromBase64String(phrase);

            // Set the key
            decryptor.Key = key;
            decryptor.IV = key;

            // create a memory stream
            using (MemoryStream decryptionStream = new MemoryStream())
            {
                // Create the crypto stream
                using (CryptoStream decrypt = new CryptoStream(decryptionStream, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    // Encrypt
                    decrypt.Write(encryptedData, 0, encryptedData.Length);
                    decrypt.Flush();
                    decrypt.Close();

                    // Return the unencrypted data
                    byte[] decryptedData = decryptionStream.ToArray();
                    return UTF8Encoding.UTF8.GetString(decryptedData, 0, decryptedData.Length);
                }
            }
        }

        public string Encrypt(string phrase)
        {
            return Encrypt(phrase, new Rfc2898DeriveBytes(PASSWORD_GUID, ENCODING.GetBytes(SALT_GUID.ToString())).GetBytes(16));
        }

        public string Encrypt<T>(string phrase, T salt)
        {
            return Encrypt(phrase, new Rfc2898DeriveBytes(PASSWORD_GUID, ENCODING.GetBytes(salt.ToString())).GetBytes(16));
        }

        private string Encrypt(string phrase, byte[] key)
        {
            AesManaged encryptor = new AesManaged();

            // Set the key
            encryptor.Key = key;
            encryptor.IV = key;

            // create a memory stream
            using (MemoryStream encryptionStream = new MemoryStream())
            {
                // Create the crypto stream
                using (CryptoStream encrypt = new CryptoStream(encryptionStream, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    // Encrypt
                    byte[] utfD1 = ENCODING.GetBytes(phrase);
                    encrypt.Write(utfD1, 0, utfD1.Length);
                    encrypt.FlushFinalBlock();
                    encrypt.Close();

                    // Return the encrypted data
                    return Convert.ToBase64String(encryptionStream.ToArray());
                }
            }
        }

        #endregion
        
    }

}